home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Cross Platform / QuickTime 4.1.2 Windows SDK / CIncludes / Endian.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-12  |  12.2 KB  |  446 lines  |  [TEXT/R*ch]

  1. /*
  2.      File:        Endian.h
  3.  
  4.      Contains:    QuickTime Interfaces
  5.  
  6.      Version:    Technology:    QuickTime 3.0
  7.                  Release:    QuickTime 4.1
  8.  
  9.      Copyright:    (c) 1997-1999 by Apple Computer, Inc., all rights reserved
  10.  
  11.      Bugs?:        For bug reports, consult the following page on
  12.                  the World Wide Web:
  13.  
  14.                      http://developer.apple.com/bugreporter/
  15.  
  16. */
  17. #ifndef __ENDIAN__
  18. #define __ENDIAN__
  19.  
  20. #ifndef __CONDITIONALMACROS__
  21.     #include <ConditionalMacros.h>
  22. #endif
  23.  
  24. #ifndef __MACTYPES__
  25.     #include <MacTypes.h>
  26. #endif
  27.  
  28.  
  29.  
  30.  
  31. #if PRAGMA_ONCE
  32. #pragma once
  33. #endif
  34.  
  35. #ifdef __cplusplus
  36. extern "C" {
  37. #endif
  38.  
  39. #if PRAGMA_IMPORT
  40. #pragma import on
  41. #endif
  42.  
  43. #if PRAGMA_STRUCT_ALIGN
  44.     #pragma options align=mac68k
  45. #elif PRAGMA_STRUCT_PACKPUSH
  46.     #pragma pack(push, 2)
  47. #elif PRAGMA_STRUCT_PACK
  48.     #pragma pack(2)
  49. #endif
  50.  
  51. /*
  52.     This file provides Endian Flipping routines for dealing with converting data
  53.     between Big-Endian and Little-Endian machines.  These routines are useful
  54.     when writing code to compile for both Big and Little Endian machines and  
  55.     which must handle other endian number formats, such as reading or writing 
  56.     to a file or network packet.
  57.     
  58.     These routines are named as follows:
  59.     
  60.         Endian<U><W>_<S>to<D>
  61.  
  62.     where
  63.         <U>    is whether the integer is signed ('S') or unsigned ('U')
  64.         <W> is integer bit width: 16, 32, or 64 
  65.         <S> is the source endian format: 'B' for big, 'L' for little, or 'N' for native
  66.         <D> is the destination endian format: 'B' for big, 'L' for little, or 'N' for native
  67.     
  68.     For example, to convert a Big Endian 32-bit unsigned integer to the current native format use:
  69.         
  70.         long i = EndianU32_BtoN(data);
  71.         
  72.     This file is set up so that the function macro to nothing when the target runtime already
  73.     is the desired format (e.g. on Big Endian machines, EndianU32_BtoN() macros away).
  74.             
  75.     If long long's are not supported, you cannot get 64-bit quantities as a single value.
  76.     The macros are not defined in that case.
  77.     
  78.     
  79.     
  80.                                 <<< W A R N I N G >>>
  81.     
  82.     It is very important not to put any autoincrements inside the macros.  This 
  83.     will produce erroneous results because each time the address is accessed in the macro, 
  84.     the increment occurs.
  85.     
  86.  */
  87. /*
  88.    Note: These functions are currently not implemented in any library
  89.          and are only listed here as function prototypes to document the macros
  90. */
  91. EXTERN_API_C( SInt16 )
  92. EndianS16_BtoN                    (SInt16                 value);
  93.  
  94. EXTERN_API_C( SInt16 )
  95. EndianS16_NtoB                    (SInt16                 value);
  96.  
  97. EXTERN_API_C( SInt16 )
  98. EndianS16_LtoN                    (SInt16                 value);
  99.  
  100. EXTERN_API_C( SInt16 )
  101. EndianS16_NtoL                    (SInt16                 value);
  102.  
  103. EXTERN_API_C( SInt16 )
  104. EndianS16_LtoB                    (SInt16                 value);
  105.  
  106. EXTERN_API_C( SInt16 )
  107. EndianS16_BtoL                    (SInt16                 value);
  108.  
  109. EXTERN_API_C( UInt16 )
  110. EndianU16_BtoN                    (UInt16                 value);
  111.  
  112. EXTERN_API_C( UInt16 )
  113. EndianU16_NtoB                    (UInt16                 value);
  114.  
  115. EXTERN_API_C( UInt16 )
  116. EndianU16_LtoN                    (UInt16                 value);
  117.  
  118. EXTERN_API_C( UInt16 )
  119. EndianU16_NtoL                    (UInt16                 value);
  120.  
  121. EXTERN_API_C( UInt16 )
  122. EndianU16_LtoB                    (UInt16                 value);
  123.  
  124. EXTERN_API_C( UInt16 )
  125. EndianU16_BtoL                    (UInt16                 value);
  126.  
  127. EXTERN_API_C( SInt32 )
  128. EndianS32_BtoN                    (SInt32                 value);
  129.  
  130. EXTERN_API_C( SInt32 )
  131. EndianS32_NtoB                    (SInt32                 value);
  132.  
  133. EXTERN_API_C( SInt32 )
  134. EndianS32_LtoN                    (SInt32                 value);
  135.  
  136. EXTERN_API_C( SInt32 )
  137. EndianS32_NtoL                    (SInt32                 value);
  138.  
  139. EXTERN_API_C( SInt32 )
  140. EndianS32_LtoB                    (SInt32                 value);
  141.  
  142. EXTERN_API_C( SInt32 )
  143. EndianS32_BtoL                    (SInt32                 value);
  144.  
  145. EXTERN_API_C( UInt32 )
  146. EndianU32_BtoN                    (UInt32                 value);
  147.  
  148. EXTERN_API_C( UInt32 )
  149. EndianU32_NtoB                    (UInt32                 value);
  150.  
  151. EXTERN_API_C( UInt32 )
  152. EndianU32_LtoN                    (UInt32                 value);
  153.  
  154. EXTERN_API_C( UInt32 )
  155. EndianU32_NtoL                    (UInt32                 value);
  156.  
  157. EXTERN_API_C( UInt32 )
  158. EndianU32_LtoB                    (UInt32                 value);
  159.  
  160. EXTERN_API_C( UInt32 )
  161. EndianU32_BtoL                    (UInt32                 value);
  162.  
  163. #if !TYPE_LONGLONG
  164. /*
  165.    Note: If these Int64 functions ever were implemented in a library,
  166.          we would need two libraries, one for compilers that
  167.          support long long and one for other compilers.
  168. */
  169. EXTERN_API_C( SInt64 )
  170. EndianS64_BtoN                    (SInt64                 value);
  171.  
  172. EXTERN_API_C( SInt64 )
  173. EndianS64_NtoB                    (SInt64                 value);
  174.  
  175. EXTERN_API_C( SInt64 )
  176. EndianS64_LtoN                    (SInt64                 value);
  177.  
  178. EXTERN_API_C( SInt64 )
  179. EndianS64_NtoL                    (SInt64                 value);
  180.  
  181. EXTERN_API_C( SInt64 )
  182. EndianS64_LtoB                    (SInt64                 value);
  183.  
  184. EXTERN_API_C( SInt64 )
  185. EndianS64_BtoL                    (SInt64                 value);
  186.  
  187. EXTERN_API_C( UInt64 )
  188. EndianU64_BtoN                    (UInt64                 value);
  189.  
  190. EXTERN_API_C( UInt64 )
  191. EndianU64_NtoB                    (UInt64                 value);
  192.  
  193. EXTERN_API_C( UInt64 )
  194. EndianU64_LtoN                    (UInt64                 value);
  195.  
  196. EXTERN_API_C( UInt64 )
  197. EndianU64_NtoL                    (UInt64                 value);
  198.  
  199. EXTERN_API_C( UInt64 )
  200. EndianU64_LtoB                    (UInt64                 value);
  201.  
  202. EXTERN_API_C( UInt64 )
  203. EndianU64_BtoL                    (UInt64                 value);
  204.  
  205. #endif  /* !TYPE_LONGLONG */
  206.  
  207. /*
  208.    These types are used for structures that contain data that is
  209.    always in BigEndian format.  This extra typing prevents little
  210.    endian code from directly changing the data, thus saving much
  211.    time in the debugger.
  212. */
  213.  
  214. #if TARGET_RT_LITTLE_ENDIAN
  215.  
  216. struct BigEndianLong {
  217.     long                             bigEndianValue;
  218. };
  219. typedef struct BigEndianLong            BigEndianLong;
  220.  
  221. struct BigEndianUnsignedLong {
  222.     unsigned long                     bigEndianValue;
  223. };
  224. typedef struct BigEndianUnsignedLong    BigEndianUnsignedLong;
  225.  
  226. struct BigEndianShort {
  227.     short                             bigEndianValue;
  228. };
  229. typedef struct BigEndianShort            BigEndianShort;
  230.  
  231. struct BigEndianUnsignedShort {
  232.     unsigned short                     bigEndianValue;
  233. };
  234. typedef struct BigEndianUnsignedShort    BigEndianUnsignedShort;
  235.  
  236. struct BigEndianFixed {
  237.     Fixed                             bigEndianValue;
  238. };
  239. typedef struct BigEndianFixed            BigEndianFixed;
  240.  
  241. struct BigEndianUnsignedFixed {
  242.     UnsignedFixed                     bigEndianValue;
  243. };
  244. typedef struct BigEndianUnsignedFixed    BigEndianUnsignedFixed;
  245.  
  246. struct BigEndianOSType {
  247.     OSType                             bigEndianValue;
  248. };
  249. typedef struct BigEndianOSType            BigEndianOSType;
  250. #else
  251.  
  252. typedef long                             BigEndianLong;
  253. typedef unsigned long                     BigEndianUnsignedLong;
  254. typedef short                             BigEndianShort;
  255. typedef unsigned short                     BigEndianUnsignedShort;
  256. typedef Fixed                             BigEndianFixed;
  257. typedef UnsignedFixed                     BigEndianUnsignedFixed;
  258. typedef OSType                             BigEndianOSType;
  259. #endif  /* TARGET_RT_LITTLE_ENDIAN */
  260.  
  261.  
  262. /*
  263.     Macro away no-op functions
  264. */
  265. #if TARGET_RT_BIG_ENDIAN
  266.     #define EndianS16_BtoN(value)                (value)
  267.     #define EndianS16_NtoB(value)                (value)
  268.     #define EndianU16_BtoN(value)                (value)
  269.     #define EndianU16_NtoB(value)                (value)
  270.     #define EndianS32_BtoN(value)                (value)
  271.     #define EndianS32_NtoB(value)                (value)
  272.     #define EndianU32_BtoN(value)                (value)
  273.     #define EndianU32_NtoB(value)                (value)
  274.     #define EndianS64_BtoN(value)                (value)
  275.     #define EndianS64_NtoB(value)                (value)
  276.     #define EndianU64_BtoN(value)                (value)
  277.     #define EndianU64_NtoB(value)                (value)
  278. #else
  279.     #define EndianS16_LtoN(value)                (value)
  280.     #define EndianS16_NtoL(value)                (value)
  281.     #define EndianU16_LtoN(value)                (value)
  282.     #define EndianU16_NtoL(value)                (value)
  283.     #define EndianS32_LtoN(value)                (value)
  284.     #define EndianS32_NtoL(value)                (value)
  285.     #define EndianU32_LtoN(value)                (value)
  286.     #define EndianU32_NtoL(value)                (value)
  287.     #define EndianS64_LtoN(value)                (value)
  288.     #define EndianS64_NtoL(value)                (value)
  289.     #define EndianU64_LtoN(value)                (value)
  290.     #define EndianU64_NtoL(value)                (value)
  291. #endif
  292.  
  293.  
  294.  
  295. /*
  296.     Map native to actual
  297. */
  298. #if TARGET_RT_BIG_ENDIAN
  299.     #define EndianS16_LtoN(value)                EndianS16_LtoB(value)
  300.     #define EndianS16_NtoL(value)                EndianS16_BtoL(value)
  301.     #define EndianU16_LtoN(value)                EndianU16_LtoB(value)
  302.     #define EndianU16_NtoL(value)                EndianU16_BtoL(value)
  303.     #define EndianS32_LtoN(value)                EndianS32_LtoB(value)
  304.     #define EndianS32_NtoL(value)                EndianS32_BtoL(value)
  305.     #define EndianU32_LtoN(value)                EndianU32_LtoB(value)
  306.     #define EndianU32_NtoL(value)                EndianU32_BtoL(value)
  307.     #define EndianS64_LtoN(value)                EndianS64_LtoB(value)
  308.     #define EndianS64_NtoL(value)                EndianS64_BtoL(value)
  309.     #define EndianU64_LtoN(value)                EndianU64_LtoB(value)
  310.     #define EndianU64_NtoL(value)                EndianU64_BtoL(value)
  311. #else
  312.     #define EndianS16_BtoN(value)                EndianS16_BtoL(value)
  313.     #define EndianS16_NtoB(value)                EndianS16_LtoB(value)
  314.     #define EndianU16_BtoN(value)                EndianU16_BtoL(value)
  315.     #define EndianU16_NtoB(value)                EndianU16_LtoB(value)
  316.     #define EndianS32_BtoN(value)                EndianS32_BtoL(value)
  317.     #define EndianS32_NtoB(value)                EndianS32_LtoB(value)
  318.     #define EndianU32_BtoN(value)                EndianU32_BtoL(value)
  319.     #define EndianU32_NtoB(value)                EndianU32_LtoB(value)
  320.     #define EndianS64_BtoN(value)                EndianS64_BtoL(value)
  321.     #define EndianS64_NtoB(value)                EndianS64_LtoB(value)
  322.     #define EndianU64_BtoN(value)                EndianU64_BtoL(value)
  323.     #define EndianU64_NtoB(value)                EndianU64_LtoB(value)
  324. #endif
  325.  
  326.  
  327.  
  328. /*
  329.     Implement ≈LtoB and ≈BtoL
  330. */
  331. #define EndianS16_LtoB(value)                ((SInt16)Endian16_Swap(value))
  332. #define EndianS16_BtoL(value)                ((SInt16)Endian16_Swap(value))
  333. #define EndianU16_LtoB(value)                ((UInt16)Endian16_Swap(value))
  334. #define EndianU16_BtoL(value)                ((UInt16)Endian16_Swap(value))
  335. #define EndianS32_LtoB(value)                ((SInt32)Endian32_Swap(value))
  336. #define EndianS32_BtoL(value)                ((SInt32)Endian32_Swap(value))
  337. #define EndianU32_LtoB(value)                ((UInt32)Endian32_Swap(value))
  338. #define EndianU32_BtoL(value)                ((UInt32)Endian32_Swap(value))
  339. #define EndianS64_LtoB(value)                ((SInt64)Endian64_Swap((UInt64)value))
  340. #define EndianS64_BtoL(value)                ((SInt64)Endian64_Swap((UInt64)value))
  341. #define EndianU64_LtoB(value)                ((UInt64)Endian64_Swap(value))
  342. #define EndianU64_BtoL(value)                ((UInt64)Endian64_Swap(value))
  343.  
  344.  
  345.  
  346.  
  347. /*
  348.     Implement low level ≈_Swap functions.
  349.     
  350.         extern UInt16 Endian16_Swap(UInt16 value);
  351.         extern UInt32 Endian32_Swap(UInt32 value);
  352.         extern UInt64 Endian64_Swap(UInt64 value);
  353.         
  354.     Note: Depending on the processor, you might want to implement
  355.           these as function calls instead of macros.
  356.     
  357. */
  358. #if TARGET_CPU_68K && TARGET_OS_MAC
  359.     #pragma parameter __D0 Endian16_Swap(__D0)
  360.     pascal UInt16 Endian16_Swap(UInt16 value)
  361.         = { 0xE158 };
  362.     
  363.     #pragma parameter __D0 Endian32_Swap (__D0)
  364.     pascal UInt32 Endian32_Swap(UInt32 value)
  365.         = { 0xE158, 0x4840, 0xE158 };
  366. #else
  367.     #define Endian16_Swap(value)                 \
  368.             (((((UInt16)value)<<8) & 0xFF00)   | \
  369.              ((((UInt16)value)>>8) & 0x00FF))
  370.     
  371.     #define Endian32_Swap(value)                     \
  372.             (((((UInt32)value)<<24) & 0xFF000000)  | \
  373.              ((((UInt32)value)<< 8) & 0x00FF0000)  | \
  374.              ((((UInt32)value)>> 8) & 0x0000FF00)  | \
  375.              ((((UInt32)value)>>24) & 0x000000FF))
  376. #endif
  377.  
  378.  
  379. #if TYPE_LONGLONG
  380.     #if TARGET_OS_WIN32
  381.         /* the inline macros crash MSDEV's optimizer on Windows. */
  382.         extern UInt64 Endian64_Swap(UInt64 value);
  383.     #elif defined(__MWERKS__) && (__MWERKS__ < 0x1800)
  384.         /* older Metrowerks compilers errored on LL suffix */
  385.         #define Endian64_Swap(value)                             \
  386.                 (((((UInt64)value)<<56) & 0xFF00000000000000)  | \
  387.                  ((((UInt64)value)<<40) & 0x00FF000000000000)  | \
  388.                  ((((UInt64)value)<<24) & 0x0000FF0000000000)  | \
  389.                  ((((UInt64)value)<< 8) & 0x000000FF00000000)  | \
  390.                  ((((UInt64)value)>> 8) & 0x00000000FF000000)  | \
  391.                  ((((UInt64)value)>>24) & 0x0000000000FF0000)  | \
  392.                  ((((UInt64)value)>>40) & 0x000000000000FF00)  | \
  393.                  ((((UInt64)value)>>56) & 0x00000000000000FF))
  394.     #else
  395.         #define Endian64_Swap(value)                             \
  396.                 (((((UInt64)value)<<56) & 0xFF00000000000000ULL)  | \
  397.                  ((((UInt64)value)<<40) & 0x00FF000000000000ULL)  | \
  398.                  ((((UInt64)value)<<24) & 0x0000FF0000000000ULL)  | \
  399.                  ((((UInt64)value)<< 8) & 0x000000FF00000000ULL)  | \
  400.                  ((((UInt64)value)>> 8) & 0x00000000FF000000ULL)  | \
  401.                  ((((UInt64)value)>>24) & 0x0000000000FF0000ULL)  | \
  402.                  ((((UInt64)value)>>40) & 0x000000000000FF00ULL)  | \
  403.                  ((((UInt64)value)>>56) & 0x00000000000000FFULL))
  404.     #endif
  405. #else
  406.     /* 
  407.         Note: When using C compilers that don't support "long long",
  408.               Endian64_Swap must be implemented as glue. 
  409.     */
  410.     #ifdef __cplusplus
  411.         inline static UInt64 Endian64_Swap(UInt64 value)
  412.         {
  413.             UInt64 temp;
  414.             ((UnsignedWide*)&temp)->lo = Endian32_Swap(((UnsignedWide*)&value)->hi);
  415.             ((UnsignedWide*)&temp)->hi = Endian32_Swap(((UnsignedWide*)&value)->lo);
  416.             return temp;
  417.         }
  418.     #else
  419.         extern UInt64 Endian64_Swap(UInt64 value);
  420.     #endif
  421. #endif
  422.  
  423.  
  424.  
  425.  
  426. #if PRAGMA_STRUCT_ALIGN
  427.     #pragma options align=reset
  428. #elif PRAGMA_STRUCT_PACKPUSH
  429.     #pragma pack(pop)
  430. #elif PRAGMA_STRUCT_PACK
  431.     #pragma pack()
  432. #endif
  433.  
  434. #ifdef PRAGMA_IMPORT_OFF
  435. #pragma import off
  436. #elif PRAGMA_IMPORT
  437. #pragma import reset
  438. #endif
  439.  
  440. #ifdef __cplusplus
  441. }
  442. #endif
  443.  
  444. #endif /* __ENDIAN__ */
  445.  
  446.